using IPTools.Core;
using Ln.Fram.Core.Extensions;
using Ln.Fram.Core.Helper;
using Ln.Rbac.Domain.Shared.OperLog;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Users;

namespace Ln.Rbac.Domain.Operlog;

public class OperLogGlobalAttribute : ActionFilterAttribute, ITransientDependency
{
	private ILogger<OperLogGlobalAttribute> _logger;
	private IRepository<OperationLogEntity> _repository;
	private ICurrentUser _currentUser;
	//注入一个日志服务
	public OperLogGlobalAttribute(ILogger<OperLogGlobalAttribute> logger, IRepository<OperationLogEntity> repository, ICurrentUser currentUser)
	{
		_logger = logger;
		_repository = repository;
		_currentUser = currentUser;
	}

	public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
	{
		var resultContext = await next();
		//执行后
		//判断标签是在方法上
		if (resultContext.ActionDescriptor is not ControllerActionDescriptor controllerActionDescriptor) return;
		//查找标签，获取标签对象
		OperLogAttribute? operLogAttribute = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
			.FirstOrDefault(a => a.GetType().Equals(typeof(OperLogAttribute))) as OperLogAttribute;
		//空对象直接返回
		if (operLogAttribute is null) return;
		////获取控制器名
		//string controller = context.RouteData.Values["Controller"].ToString();
		////获取方法名
		//string action = context.RouteData.Values["Action"].ToString();
		//获取Ip
		string ip = resultContext.HttpContext.GetClientIp();
		//根据ip获取地址
		string location = "";
		try
		{
			var ipTool = IpTool.Search(ip);
			location = ipTool.Province + " " + ipTool.City;
		}
		catch
		{
			location = "搜索地址失败，可能是内网地址:" + ip;
		}
		//日志服务插入一条操作记录即可
		var logEntity = new OperationLogEntity();
		logEntity.OperIp = ip;
		//logEntity.OperLocation = location;
		logEntity.OperType = operLogAttribute.OperType;
		logEntity.Title = operLogAttribute.Title;
		logEntity.RequestMethod = resultContext.HttpContext.Request.Method;
		logEntity.Method = resultContext.HttpContext.Request.Path.Value;
		logEntity.OperLocation = location;
		logEntity.OperUser = _currentUser.UserName;
		if (operLogAttribute.IsSaveResponseData)
		{
			if (resultContext.Result is ContentResult result && result.ContentType == "application/json")
				logEntity.RequestResult = result.Content?.Replace("\r\n", "").Trim();
			if (resultContext.Result is JsonResult result2)
				logEntity.RequestResult = result2.Value?.ToString();
			if (resultContext.Result is ObjectResult result3)
				logEntity.RequestResult = JsonHelper.ObjToStr(result3.Value);
		}
		if (operLogAttribute.IsSaveRequestData)
		{
			//不建议保存，吃性能
			//保存请求参数
			logEntity.RequestParam = JsonConvert.SerializeObject(context.ActionArguments);
		}
		await _repository.InsertAsync(logEntity);
	}
}
